import React, { ReactNode, useState, useRef, useEffect, useCallback } from 'react';
import { bem, commonUtils } from '@/utils';
import './swiper.scss';
import SwiperItem from './swiperItem';
import SwiperNav from './SwiperNav';

export interface SwiperProps {
    mousewheel: boolean;
    children?: ReactNode;
    onChange?: (index: number) => void;
    navTabShow?: boolean;
    scrollNavShow?: boolean;
    navMoreContent?: ReactNode;
    offset?: number;
}

const defaultProps = {
    mousewheel: false,
    onChange: (index: number) => undefined,
    offset: 0,
    bannerHeight: 375,
    headerFadeRadio: {
        start: .65,
        end: .78
    },
}

const Swiper: React.FC<SwiperProps> & { Item: typeof SwiperItem } = (props) => {
    const {
        mousewheel,
        onChange,
        children,
        offset,
        scrollNavShow,
        navTabShow,
        bannerHeight,
        navMoreContent,
        headerFadeRadio,
        ...rest
    } =
    {
        ...defaultProps,
        ...props
    }

    const b = bem('swiper');

    const childArray = React.Children.toArray(children);
    const [activeTab, setActiveTab] = useState(Number);

    const [rootMargin, setRootMargin] = useState("0px");
    const [headHeight, setHeadHeight] = useState(offset);

    const observedRefs = useRef<HTMLDivElement[]>([]);
    const obsMap = new Map<Element, Number>();
    // 改进后的高度获取
    const observedElements = useCallback(() => {
        return Array.from(observedRefs.current);
    }, []);

    const [firstActiveElement, setFirstActiveElement] = useState<Element | null>(null);

    const activeElementCallback = (el: Element | null) => {
        if (!el) {
            return;
        }
        const value = obsMap.get(el) ?? 0;
        const currentIndex = Number(value);
        if (currentIndex !== activeTab) {
            // console.log(currentIndex);
            setActiveTab(currentIndex);
            // 触发onChange
            onChange?.(currentIndex);
        }
    }

    useEffect(() => {
        activeElementCallback(firstActiveElement);
    }, [activeElementCallback, firstActiveElement]);


    useEffect(() => {
        setRootMargin(`-${headHeight}px 0px 0px 0px`);
    }, [rootMargin]);

    useEffect(() => {
        if (typeof IntersectionObserver === "undefined") {
            // SSR or old browser.
            return;
        }
        // 鼠标滚轮事件
        if (!mousewheel) {
            return;
        }

        const obsElements = observedElements();
        const activeElementMap = new Map<Element, boolean>();

        const observer = new IntersectionObserver(
            (entries) => {
                entries.forEach((entry) => {
                    activeElementMap.set(entry.target, entry.isIntersecting);
                });
                const activeItem = Array.from(activeElementMap.entries())
                    .filter(([, value]) => value)
                    .map(([key]) => key);

                setFirstActiveElement(activeItem[0] ?? null);
            },
            {
                rootMargin,
                threshold: [0.0, 1.0],
            }
        );

        obsElements.forEach((element) => {
            activeElementMap.set(element, false);
            observer.observe(element);
        });

        return () => observer.disconnect();
    }, [rootMargin, observedElements(), activeElementCallback]);

    const handlerNavActive = (index: number) => {
        const target = observedRefs.current[index];
        if (!target) {
            return;
        }
        observedRefs.current[index]?.scrollIntoView({
            behavior: "smooth",
            block: "start",
        });

        if (!mousewheel) {
            setFirstActiveElement(target);
        }
    }

    return (
        <div className={b()}>
            <SwiperNav menuList={[
                {
                    title: '商品'
                },
                {
                    title: '评价',
                },
                {
                    title: '详情'
                }]
            }
                onHandlerActive={handlerNavActive}
                activeTab={activeTab}
                scrollNavShow={scrollNavShow}
                navMoreContent={navMoreContent}
            />

            <div className={b('wrap')} >
                {
                    childArray?.map((child, i) => {
                        if (!React.isValidElement(child)) {
                            return null;
                        }
                        if (!child.props) {
                            return;
                        }
                        return (
                            <SwiperItem
                                key={i}
                                id={i}
                                navShow={child.props.navShow}
                                children={child.props.children}
                                title={child.props.title}
                                ref={(el) => {
                                    if (el) {
                                        observedRefs.current[i] = el;
                                        obsMap.set(el, i);
                                    }
                                }}
                            />
                        )
                    })
                }
            </div>

        </div>

    )
}

Swiper.Item = SwiperItem;

export default Swiper;